/* registerdef.cpp
 * Class RegisterDef
 * Very simple class to contain information about a register
 * with some convenience functions to make life a bit easier
 * Declared as a Qt Metatype so that you can use it in QLists
 */

#include "registerdef.h"

//Address must be initialised to -1 or an empty RegisterDef will actually equal the
// very first register (usually DBG_SRC or something)
RegisterDef::RegisterDef()
{
    m_name = "";
    m_address = -1;
    m_flags = 0;
    m_fValue = 0.0;
    m_iValue = 0;
    m_sValue = "";
}

//To be allowed in QLists a copy constructor is needed
RegisterDef::RegisterDef(const RegisterDef &other) {
    m_name = other.m_name;
    m_address = other.m_address;
    m_flags = other.m_flags;

    m_fValue = other.m_fValue;
    m_iValue = other.m_iValue;
    m_sValue = other.m_sValue;
}

//Initialise only the address - used for comparisons
RegisterDef::RegisterDef( int address )
{
    m_name = "";
    m_address = address;
    m_flags = 0;
    m_fValue = 0.0;
    m_iValue = 0;
    m_sValue = "";
}

//Initialise only the name - used for comparisons
RegisterDef::RegisterDef( QString name )
{
    m_name = name;
    m_address = -1;
    m_flags = 0;
    m_fValue = 0.0;
    m_iValue = 0;
    m_sValue = "";
}

//Create a fully-featured register
RegisterDef::RegisterDef( QString name, int address, int flags ) {
    m_name = name;
    m_address = address;
    m_flags = flags;
    m_fValue = 0.0;
    m_iValue = 0;
    m_sValue = "";
}

RegisterDef::~RegisterDef() {
    //nothing to do
}

QString RegisterDef::name() const {
    return m_name;
}

int RegisterDef::flags() const {
    return m_flags;
}

int RegisterDef::address() const {
    return m_address;
}

float RegisterDef::fValue() const {
    return m_fValue;
}

int RegisterDef::iValue() const {
    return m_iValue;
}

QString RegisterDef::sValue() const {
    return m_sValue;
}

//Convenience function to set the value to the appropriate place depending on the register type
void RegisterDef::setValue(QString value) {
    switch (this->regtype()) {
        case REG_STRING:
            m_sValue = value;
            break;
        case REG_INTEGER:
            m_iValue = value.toInt();
            break;
        case REG_FLOAT:
            m_fValue = value.toFloat();
            break;
        default:
            m_sValue = value;
            break;
    }
}

//Convenience function to get the value as a QString regardless of the register type
QString RegisterDef::getValue() const {
    switch (this->regtype()) {
        case REG_STRING:
            return m_sValue;
            break;
        case REG_INTEGER:
            return QString::number(m_iValue);
            break;
        case REG_FLOAT:
            return QString::number(m_fValue);
            break;
        default:
            return m_sValue;
    }
}

//Convenience function to get the value as a double for integer and double registers
// used in the graphing functions
double RegisterDef::getfValue() const {
    switch (this->regtype()) {
        case REG_STRING:
            return 0.0;
            break;
        case REG_INTEGER:
            return m_iValue;
            break;
        case REG_FLOAT:
            return m_fValue;
            break;
        default:
            return 0.0;
    }
}

RegisterType RegisterDef::regtype() const {
    if ( m_flags & FLAG_STRING )
        return REG_STRING;
    if ( m_flags & FLAG_INTEGER )
        return REG_INTEGER;
    if ( m_flags & FLAG_FLOAT )
        return REG_FLOAT;

    return REG_UNKNOWN;
}

bool RegisterDef::loggable() const {
    if ( m_flags & FLAG_CAN_BE_LOGGED ) {
        return true;
    } else {
        return false;
    }
}

bool RegisterDef::readable() const {
    if ( m_flags & FLAG_READ ) {
        return true;
    } else {
        return false;
    }
}

bool RegisterDef::writeable() const {
    if (  m_flags & FLAG_WRITE ) {
        return true;
    } else {
        return false;
    }
}

bool RegisterDef::hidden() const {
    if (  m_flags & FLAG_HIDDEN ) {
        return true;
    } else {
        return false;
    }
}

bool RegisterDef::system() const {
    if (  m_flags & FLAG_SYSTEM ) {
        return true;
    } else {
        return false;
    }
}

//overload of == operator
//Needed for QList::contains() and QList::indexOf() functions
// if either the name OR address matches, return true
bool RegisterDef::operator==( const RegisterDef &other ) const {
    return ((other.m_address == m_address) || (other.m_name == m_name));
}
